package com.qyer.commons.utils;

import com.qyer.commons.exception.DBException;
import com.qyer.commons.persistence.DBResourceManager;
import org.apache.commons.dbutils.DbUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * User: Z J Wu Date: 2015/03/23 Time: 11:04 Package: com.qyer.dsp.utils
 */
public class DBUtils {

  private static final Logger LOGGER = LoggerFactory.getLogger(DBUtils.class);

  public static Connection tryConnect(DBResourceManager manager, String info) throws DBException {
    return tryConnect(manager.getDataSource(), 10, info);
  }

  public static Connection tryConnect(DataSource ds, int tryTimes, String info) throws DBException {
    Connection conn = null;
    int getConnectionCount = 0;
    Exception cause = null;
    boolean ok = false;
    while (getConnectionCount < tryTimes) {
      ++getConnectionCount;
      try {
        conn = ds.getConnection();
      } catch (SQLException e) {
        cause = e;
        LOGGER
          .error("Cannot get connection({}) from connection pool({}).", getConnectionCount, info);
        continue;
      }
      try {
        if (conn == null || conn.isClosed()) {
          cause = new SQLException("Connection is closed.");
          LOGGER.warn("Connection({}) is invalid({}).", info, getConnectionCount);
          continue;
        }
      } catch (SQLException e) {
        cause = e;
        LOGGER.warn("Cannot validate connection({}) after {} times.", info, getConnectionCount);
        continue;
      }
      ok = true;
      break;
    }
    if (ok) {
      return conn;
    } else {
      throw new DBException(
        "Cannot get connection after " + String.valueOf(getConnectionCount) + " times.", cause);
    }
  }

  public static void closeAllQuietly(Connection connection, PreparedStatement preparedStatement,
                                     ResultSet resultSet) {
    DbUtils.closeQuietly(resultSet);
    DbUtils.closeQuietly(preparedStatement);
    DbUtils.closeQuietly(connection);
  }

  public static void closeAllQuietly(Connection connection, PreparedStatement preparedStatement) {
    closeAllQuietly(connection, preparedStatement, null);
  }

  public static void rollback(Connection connection) throws DBException {
    if (connection != null) {
      try {
        connection.rollback();
      } catch (SQLException e) {
        throw new DBException("Cannot rollback", e);
      }
    }
  }

}
